package com.tbit.uqbike.service.business.impl;

import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.AddCountFee;
import com.tbit.uqbike.object.pojo.Machine;
import com.tbit.uqbike.object.pojo.MachineFeeBound;
import com.tbit.uqbike.service.business.MachineFeeBoundService;
import com.tbit.uqbike.webmanager.dao.core.AddCountFeeDao;
import com.tbit.uqbike.webmanager.dao.core.MachineDao;
import com.tbit.uqbike.webmanager.dao.core.MachineFeeBoundDao;
import com.tbit.uqbike.webmanager.util.DateUtils;
import com.tbit.uqbike.webmanager.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 设备计费规则绑定Service业务层处理
 *
 * @author jing
 * @date 2021-06-01
 */
@Service
public class MachineFeeBoundServiceImpl implements MachineFeeBoundService {
    @Autowired
    private MachineFeeBoundDao machineFeeBoundDao;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private AddCountFeeDao addCountFeeDao;

    /**
     * 查询设备计费规则绑定列表
     *
     * @param machineFeeBound 设备计费规则绑定
     * @return 设备计费规则绑定
     */
    @Override
    public List<MachineFeeBound> selectMachineFeeBoundList(MachineFeeBound machineFeeBound) {
        if (StringUtils.isNotNull(machineFeeBound.getUserCode())) {
            machineFeeBound.setUserCodes(StringUtils.str2List(machineFeeBound.getUserCode(), ",", true, true));
        }
        return machineFeeBoundDao.selectMachineFeeBoundList(machineFeeBound);
    }

    /**
     * 新增设备计费规则绑定
     *
     * @param machineFeeBound 设备计费规则绑定
     * @return 结果
     */
    @Override
    //@Transactional
    public Map<String, Object> insertMachineFeeBound(MachineFeeBound machineFeeBound) {
        Map<String, Object> result = new HashMap<>();
        List<String> userCodes = StringUtils.str2List(machineFeeBound.getUserCode(), ",", true, true);
        /*判断计费规则区域和车辆区域是否一致*/
        List<Machine> machines = checkVehicleOutSideArea(userCodes, machineFeeBound.getFeeId());
        Map<String, Machine> map = machines.stream().collect(Collectors.toMap(Machine::getUserCode, Function.identity(), (x1, x2) -> x1));
        /*筛选已添加到(machinefeebound)的设备*/
        List<String> exist = machineFeeBoundDao.selectMachineFeeBoundList(new MachineFeeBound(machines.stream().map(Machine::getUserCode).collect(Collectors.toList()))).stream().map(MachineFeeBound::getUserCode).distinct().collect(Collectors.toList());
        Map<String, String> existMap = exist.stream().collect(Collectors.toMap(Function.identity(), Function.identity()));
        //筛选不存在machine表的车辆
        List<String> notExist = new ArrayList<>();
        List<MachineFeeBound> list = new ArrayList<>();
        Date nowDate = DateUtils.getNowDate();
        userCodes.forEach(code -> {
            if (!existMap.containsKey(code)) {
                if (map.containsKey(code)) {
                    list.add(new MachineFeeBound(map.get(code).getMachineId(), machineFeeBound.getFeeId(), nowDate));
                } else {
                    notExist.add(code);
                }
            }
        });
        if (StringUtils.isNotEmpty(list)) {
            machineFeeBoundDao.batchInsertMachineFeeBound(list.get(0), list);
        }
        result.put("notExist", notExist);
        result.put("exist", exist);
        return result;
    }


    /**
     * 批量删除设备计费规则绑定
     *
     * @param machineFeeBound 需要删除的设备计费规则绑定ID
     * @return 结果
     */
    @Override
    public Map<String, Object> deleteMachineFeeBoundByIds(MachineFeeBound machineFeeBound) {
        Map<String, Object> result = new HashMap<>();
        List<String> userCodes = StringUtils.str2List(machineFeeBound.getUserCode(), ",", true, true);
        /*判断计费规则区域和车辆区域是否一致*/
        List<Machine> machines = checkVehicleOutSideArea(userCodes, machineFeeBound.getFeeId());
        Map<String, Machine> map = machines.stream().collect(Collectors.toMap(Machine::getUserCode, Function.identity(), (x1, x2) -> x1));
        /*筛选已添加到(machinefeebound)的设备*/
        List<MachineFeeBound> bounds = machineFeeBoundDao.selectMachineFeeBoundList(new MachineFeeBound(machines.stream().map(Machine::getUserCode).collect(Collectors.toList())));
        List<String> exist = bounds.stream().map(MachineFeeBound::getUserCode).distinct().collect(Collectors.toList());
        Map<String, String> existMap = exist.stream().collect(Collectors.toMap(Function.identity(), Function.identity()));
        List<String> notExist = new ArrayList<>();
        List<String> notBound = new ArrayList<>();
        userCodes.forEach(code -> {
            if (map.containsKey(code)) {
                if (!existMap.containsKey(code)) {
                    notBound.add(code);
                }
            } else {
                notExist.add(code);
            }
        });
        if (StringUtils.isNotEmpty(exist)) {
            machineFeeBoundDao.deleteMachineFeeBoundByIds(bounds.stream().map(MachineFeeBound::getBoundId).collect(Collectors.toList()).toArray(new Integer[bounds.size()]));
        }
        result.put("notExist", notExist);
        result.put("notBound", notBound);
        return result;
    }

    @Override
    public List<Machine> checkVehicleOutSideArea(List<String> userCodes, Integer feeId) {
        List<Machine> machines = machineDao.checkUserCodeExist(userCodes);
        List<AddCountFee> machineFeeList = addCountFeeDao.getMachineFeeList(new AddCountFee(feeId));
        /*判断计费规则是否存在*/
        if (StringUtils.isEmpty(machineFeeList)) {
            throw new BaseException(SystemCodeEnum.FEE_NOT_EXIST);
        }
        /*判断计费规则区域和车辆区域是否一致*/
        List<Integer> accountIds = machines.stream().map(Machine::getAccountId).distinct().collect(Collectors.toList());
        if (StringUtils.isEmpty(accountIds) || accountIds.size() != 1 || !accountIds.get(0).equals(machineFeeList.get(0).getAccountId())) {
            throw new BaseException(SystemCodeEnum.VEHICLES_OUTSIDE_THE_AREA);
        }
        return machines;
    }

}
